package com.kimoge.spring6.iocimpl.core.impl;

import com.kimoge.spring6.iocimpl.annotation.Bean;
import com.kimoge.spring6.iocimpl.annotation.Di;
import com.kimoge.spring6.iocimpl.core.ApplicationContext;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author kimoge
 * @date 2025/8/28
 * @description
 */
public class MyApplicationContext implements ApplicationContext {

    private String scanPath;
    private String rootPath;
    private Map<Class, Object> beans = new HashMap<Class, Object>();

    public MyApplicationContext(String scanPath) {
        //扫描路径，创建bean
        this.scanPath = scanPath;
        try {
            createBean();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> T getBean(String name, Class<T> requiredType) throws Exception {
        return (T) beans.get(requiredType);
    }

    @Override
    public void createBean() throws Exception {
//        System.out.println(this.scanPath);
        String packagePath = this.scanPath.replaceAll("\\.", "\\\\");
//        System.out.println("packagePath = " + packagePath);
//        读取路径
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        Enumeration<URL> resources = classLoader.getResources(packagePath);
        while (resources.hasMoreElements()) {
            URL url = resources.nextElement();
//            System.out.println(url);
            // 解决com%5ckimoge%5cspring6%5ciocimpl中的%问题
            String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
//            System.out.println(decode);
            rootPath = filePath.substring(0, filePath.length() - packagePath.length());
            loadBean(new File(filePath));
        }
    }

    @Override
    public void loadBean(File file) throws Exception {
//        循环加载bean
        if (!file.isDirectory()) {
//            System.out.println(rootPath);
            String aClassString = file.getAbsoluteFile().toString()
                    .substring(rootPath.length()-1)
                    .replaceAll(".class","")
                    .replaceAll("\\\\", "\\.");
//            System.out.println(aClassString);
            Class<?> aClass = Class.forName(aClassString);
            // aClass不是接口
            if (!aClass.isInterface()){
                Bean annotation = aClass.getAnnotation(Bean.class);
                // aClass上有@Bean注解
                if (annotation != null) {
                    Object object = aClass.getConstructor().newInstance();

                    // 循环查找aClass的属性，如果有@Di注解，则需要注入属性
                    for (Field declaredField : aClass.getDeclaredFields()) {
                        if (declaredField.isAnnotationPresent(Di.class)) {
                            declaredField.setAccessible(true);
                            // 注意：此处决定了@Di注解注释的属性声明只有在没有接口实现时才能为实现类的类型
                            declaredField.set(object, beans.get(declaredField.getType()));
                        }
                    }


                    // 单例模式  一个接口只能有一个实现类有注解Bean,一个类只能有一个对象
                    if (aClass.getInterfaces().length > 0) {
                    //有接口则用接口作为map的key
                        beans.put(aClass.getInterfaces()[0], object);
//                        System.out.println(aClass.getInterfaces()[0]);
                    }else {
                    //否则用类作为key
                        beans.put(aClass, object);
                    }
                }
            }
            return;
        }

        for (File listFile : file.listFiles()) {
            loadBean(listFile);
        }
    }


}
